/*! \copyright 2024 Zorxx Software. All rights reserved.
 *  \license This file is released under the MIT License. See the LICENSE file for details.
 *  \brief rtci2c library esp-idf example application
 */

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "freertos/queue.h"
#include "esp_freertos_hooks.h"
#include "freertos/semphr.h"
#include "esp_system.h"

#include <errno.h>
#include "esp_err.h"
#include "esp_log.h"

#include "driver/gpio.h"
#include "soc/gpio_num.h"
#include "myiic.h" 

#include "gzp6816d.h"

#define TAG "gzp6816d"

#define GZP6816D_SCL_IO          (gpio_num_t)39         /*!< gpio number for I2C master clock */
#define GZP6816D_SDA_IO          (gpio_num_t)40         /*!< gpio number for I2C master data  */
#define GZP6816D_FREQ_HZ    		    100000          /*!< I2C master clock frequency */
#define GZP6816D_ADDRESS 				0x78


#define ADC_FULL_SCALE  16777216UL    // 24位ADC满量程值 (2^24)
// 定义最小气压值为30.0
#define PMIN 30.0f
// 定义最大气压值为110.0
#define PMAX 110.0f
// 定义数字输出的最小值为1677721.0
#define DMIN  (ADC_FULL_SCALE * 0.1f)
// 定义数字输出的最大值为15099949.0
#define DMAX  (ADC_FULL_SCALE * 0.9f)

// // 定义温度换算参数
// #define TMIN -50.0f  // 温度下限
// #define TMAX 150.0f  // 温度上限
// #define TEMP_MAX 16777216  // ADC 温度最大值


#define CONST_PF 0.1902630958	       //(1/5.25588f) Pressure factor
#define FIX_TEMP 25				       // Fixed Temperature. ASL is a function of pressure and temperature, but as the temperature changes so much (blow a little towards the flie and watch it drop 5 degrees) it corrupts the ASL estimates.
								       // TLDR: Adjusting for temp changes does more harm than good.
/*
 * Converts pressure to altitude above sea level (ASL) in meters
*/
static float bmp280PressureToAltitude(float* pressure)
{
    if (*pressure>0)
    {
        return((pow((1015.7f/ *pressure),CONST_PF)-1.0f)*(FIX_TEMP+273.15f))/0.0065f;
    }
    else
    {
        return 0;
    }
}


esp_err_t gzp6816d_init(void)
{
	my_iic_init();

	return ESP_OK;		
}
static unsigned char gzp6816d_IsBusy(void)
{
	unsigned char status;
	//I2C_ReadData(I2C_address , &status, 1);
	
	vTaskDelay(100 / portTICK_PERIOD_MS);	
	my_iic_read_byte(GZP6816D_ADDRESS,0xff,(uint8_t *)&status);//非标准i2c时序
    printf("status0 = 0x%02x\r\n",status);
	status = (status >> 5) & 0x01;
    printf("status1 = 0x%02x\r\n",status);
    
	return status;	
}

void gzp6816d_read_sensordata(SensorData *sensor_data)
{
    unsigned char buffer[6] = {0};
    buffer[0] = 0xAC;//0XAC和0XB0-BF命令一样只是设置不同的过采样率
                     // 温度过采样率  0：4x 1：8x
                     // 压力过采样率  000：128x  001：64x  010：32x  011：16x  100：8x  101：4x  110：2x  111：1x
	//换醒传感器
	//I2C_WriteData(I2C_address, buffer, 1);
	my_iic_write_bytes(GZP6816D_ADDRESS,0xAC,0,&buffer[0]);//非标准i2c时序
	vTaskDelay(10 / portTICK_PERIOD_MS);
	while(1)//等待空闲
	{     
		if(gzp6816d_IsBusy())
		{
			vTaskDelay(300 / portTICK_PERIOD_MS);
		}
		else
			break;
	}
	//读取数据
    //I2C_ReadData(I2C_address, buffer, 6);
     my_iic_read_nbytes(GZP6816D_ADDRESS, 6, (uint8_t *)&buffer[0]);//非标准i2c时序
       
    sensor_data->pressure_AD = (unsigned long)((((unsigned long)buffer[1]) << 16) | (((unsigned int)buffer[2]) << 8) | ((unsigned char)buffer[3]));
    sensor_data->temperature_AD = ((unsigned int)buffer[4] << 8) | (buffer[5] << 0);
    sensor_data->pressure_kpa = (float) ((PMAX-PMIN)/(DMAX-DMIN)*(sensor_data->pressure_AD-DMIN)+PMIN);	 //单位：KPa
    sensor_data->pressure = (double) (sensor_data->pressure_kpa * 1000.0);
    sensor_data->temperature = ((float)sensor_data->temperature_AD / 65536 * 19000 - 4000) / 100.0;

    #if 1
    // 调试打印传感器数据
    printf(" status   = %02X\r\n", buffer[0]);
    printf("buffer[1] = %02X\r\n", buffer[1]);
    printf("buffer[2] = %02X\r\n", buffer[2]);
    printf("buffer[3] = %02X\r\n", buffer[3]);
    printf("buffer[4] = %02X\r\n", buffer[4]);
    printf("buffer[5] = %02X\r\n", buffer[5]);
    printf("pressure_AD = %ld\r\n", sensor_data->pressure_AD);
    printf("temperature_AD = %ld\r\n", sensor_data->temperature_AD);
    printf("pressure is %.2f Pa\r\n", sensor_data->pressure);
    printf("temperature is %.2f C\r\n", sensor_data->temperature);
    #endif	
}
void gzp6816d_task(void *pvParameter)
{
	SensorData sensor_data;
	
	while(1)
	{
		gzp6816d_read_sensordata(&sensor_data);
		//读取的传感器数据
	    #if 1
	    ESP_LOGI(TAG,"pressure_AD = %ld\r\n", sensor_data.pressure_AD);
	    ESP_LOGI(TAG,"temperature_AD = %ld\r\n", sensor_data.temperature_AD);
	    ESP_LOGI(TAG,"pressure is %.2f Pa\r\n", sensor_data.pressure);
	    ESP_LOGI(TAG,"temperature is %.2f C\r\n", sensor_data.temperature);
	    //下面3种转换方法均有误差
		//气压转海拔公式1
		//大气压会随着高度的提升而下降,其关系为“每提高12m,大气压下降1mmHg(1笔升水银柱)或者每上升9m,大气压降低100Pa.
		//标准大气压为1013.25百帕(hpa),所以,海拔高度为h:
		//h=(1013.25-970)*9=389.25(米).
		ESP_LOGI(TAG,"1 high is %.2fm\r\n",(1013.25-(sensor_data.pressure/100))*9 );	    
	    
        //气压转海拔公式2	    	    
	    //BMP280是一种数字式气压、温度传感器，它能够提供高度准确的大气压和温度读数。在进行大气压海拔换算时，
	    //我们需要采用气压高度公式：h = (1 - (p/1013.25)^0.19029) x 44330.8，其中h为海拔高度（单位：米），p为当前气压（单位：百帕）。
	    //需要注意的是，此公式仅适用于海拔高度在-500至9000米之间的范围内

		float high=(1 -pow(((sensor_data.pressure/100)/1013.25), 0.19029)) * 44330.8;
		
		ESP_LOGI(TAG,"2 high is %.2fm\r\n", high);

        //气压转海拔公式3
		high=sensor_data.pressure/100;//转为百帕(hpa)
		ESP_LOGI(TAG,"3 high is %.2fm\r\n", bmp280PressureToAltitude(&high));	
			
	    #endif			
		vTaskDelay(2000 / portTICK_PERIOD_MS);

	}	
}
void gzp6816d_example(void)
{
	ESP_ERROR_CHECK(gzp6816d_init());
	
    xTaskCreate(&gzp6816d_task, "gzp6816d", 4096, NULL,2,NULL);	
}


